﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "GbmpPasteAction.h"
#include <map>


#include "IDocument.h"
#include "IUiView.h"
#include "UiCommonDialog.h"
#include "IUiDocument.h"
#include "IUiDocumentViewManager.h"

#include "ISelection.h"
#include "IPickPointAction.h"
#include "Vector3dUtils.h"
#include "IModelView.h"
#include "UiViewUtils.h"
#include "GbmpModelViewUtil.h"
#include "IEditModeCopyPasteComponent.h"
#include "IUserTransaction.h"
#include "FamilyLoadOptionsWithUI.h"
#include "IFamily.h"
#include "FamilyUtils.h"
#include "GbmpMoveUtils.h"
#include "IElementViewSpecificShapeComponent.h"
#include "IGraphicsNodeReference.h"
#include "IGraphicsElementShape.h"
#include "IGraphicsLine.h"
#include "IElementBasicInformation.h"
#include "IRegenerator.h"
#include "../CopyPaste/ClipBoard.h"
#include "../CopyPaste/ClipBoardUtils.h"
#include "IElementPosition.h"
#include "LevelUtils.h"
#include "IInstance.h"
#include "IHighlights.h"
#include "StructureInstanceLevelUtils.h"
#include "UIRenderUtils.h"
#include "GbmpBuiltInCategoryUniIdentitiesNew.h"
#include "IElementShapeHandleBehavior.h"
#include "IElementShapeHandle.h"
#include "IGraphicsStyleData.h"
#include "IGraphicsStyle.h"
#include "ClipBoardShapeHandleBehavior.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

#define ID_CMD_MOVE_INSERT_POINT_FOR_PASTE L"gmMoveMoveInsertPointForPasteCmd"
using namespace std;
using namespace gcmp;

CREATE_DEBUG_MODE(GbmpPasteHelperRectSmartColor, L"粘贴HelperRect开启智能反色", gcmp::DebugModeGroup::DMGT_RENDERING, L"GDMPLab", L"2023-12-20", L"启用此模式后粘贴HelperRect开启智能反色");

namespace
{
    //临时解决GmModel依赖于GmModelFamily的问题
    //(TODO: 临时方案，后续会改进得更加合理）
    IFamily* LoadFamily_Temp(IDocument* pDoc, const std::wstring& filePathName)
    {
        std::wstring errorMsg;
        FamilyLoadOptionsWithUI familyLoadOptionsImpl;
        return quick_cast<IFamily>(gcmp::FamilyUtils::LoadFamily(pDoc, filePathName, errorMsg, &familyLoadOptionsImpl));
    }
}

GbmpPasteAction::GbmpPasteAction()
    :m_pickedPt()
    ,m_isUserCancelled(false)
    ,m_opUserTransaction(nullptr)
    ,m_pastedElementIds()
    ,m_opSourceHelperRect(nullptr)
    ,m_opTargetHelperRect(nullptr)
    ,m_insertPtId(ElementId::InvalidID)
{
    //TODO: 临时方案
    ClipBoard * pClipBoard = ClipBoard::Get();
    DBG_WARN_UNLESS(pClipBoard, L"获取默认的粘贴板管理器失败",L"GDMPLab",L"2024-03-30");
    pClipBoard->SetLoadFamilyCallBack(LoadFamily_Temp);
}

GbmpPasteAction::~GbmpPasteAction()
{
    IUiDocument* pUIDoc = IUiDocumentViewManager::Get()->GetCurrentUiDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUIDoc, L"pUIDoc为空",L"GDMPLab",L"2024-03-30");

    IDocument* pDoc = pUIDoc->GetDbDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    ClearInsertPt(pDoc);
}

void GbmpPasteAction::OnChildActionFinished(IUiView* pCurrentView, const ActionOutput& childActionReturnParam)
{ 
    PickPastePointActionFinished(pCurrentView, childActionReturnParam.FinishStatus); 
}

//启动获取粘贴点的Action
void GbmpPasteAction::StartPickPastePointAction(IUiView* pCurrentView)
{
    //显示一个目标粘贴位置的矩形
    InitTargetHelperRect(pCurrentView);

    vector<wstring> activatableCommands;
    activatableCommands.push_back(ID_CMD_MOVE_INSERT_POINT_FOR_PASTE);
    OwnerPtr<IPickPointAction> upPickPastePointAction = IPickPointAction::Create( 
        PickPointExchangeData(&m_pickedPt, &m_isUserCancelled, &m_pickedPoints, nullptr, &activatableCommands, PickPointExchangeData::SnapPlaneType::WorkPlane, true)
        , IPickPointAction::CreateMoveCallback(&GbmpPasteAction::MouseMoveUpdate, this));
    upPickPastePointAction->SetCursorType(CursorType::CrossCursor);
    StartChildAction(TransferOwnership(upPickPastePointAction));
}

//获取粘贴点的Action结束
void GbmpPasteAction::PickPastePointActionFinished(IUiView* pCurrentView, ActionFinishStatus eFinishStatus)
{
    IUiDocument* pUIDoc = pCurrentView->GetUiDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUIDoc, L"pUIDoc为空",L"GDMPLab",L"2024-03-30");

    IModelView* pModelView = pCurrentView->GetModelView();

    IDocument* pDoc = pUIDoc->GetDbDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    Vector3d lbSource = m_opSourceHelperRect->GetCorners()[0]; 
    Vector3d lbTarget = m_opTargetHelperRect->GetCorners()[0];

    ClipBoard * pClipBoard = ClipBoard::Get();
    DBG_WARN_UNLESS(pClipBoard, L"获取默认的粘贴板管理器失败",L"GDMPLab",L"2024-03-30");

    Coordinate3d localCoor = pClipBoard->GetLocalCoordinate();
    Vector3d lbSourceLocal = localCoor.GetLocalPoint(lbSource);
    Vector3d lbTargetLocal = localCoor.GetLocalPoint(lbTarget);
    Vector3d offsetLocal = lbTargetLocal - lbSourceLocal;
    //在局部坐标系中做XY方向的偏移
    Vector3d offset = localCoor.GetWorldVector(Vector3d(offsetLocal.X(), offsetLocal.Y(), 0));
    //粘贴结束，清理临时对象
    ClearSourceHelperRect();
    ClearTargetHelperRect();

    //用户取消了
    if (eFinishStatus == ActionFinishStatus::Cancelled)
    {
        //此时需要回滚事务（清理预览的粘贴对象）
        m_opUserTransaction->Rollback();

        UpdateView();
        ActionCancelled();

        return;
    }

    //=====================================================================
    //执行粘贴工作(其实就是把预览的对象集合移动到目标位置)
    //将粘贴结果加入选择集，显示为选择状态
    GbmpMoveUtils::MoveElementsForcely(pDoc, m_pastedElementIds, offset, pModelView);

    //-----------------------------------------------------------------------------------
    //粘贴成功后：
    // (1) 约束解算
    // (2) 将粘贴结果加入选择集，显示为选择状态
    // (3) 关联关系更新
    //-----------------------------------------------------------------------------------
    //必须解算一下，因为如果Element上有约束的话，后面的解算还是按原来的位置解算的
    //目前做法是粘贴完成后：原来对象之间的相对位置关系和关联关系都是保持的
    //
    //如果是这样的理想状况，调用和不调用约束解算都一样。
    //另外，应该不用手动调用SolverHelper::ValidateConstraints()，
    //如果是在族文档里，ut.Commit()时会自动调用SolverHelper::ValidateConstraints()，不需要手动调用。
    //如果是项目文档，文档中目前没有约束，也不用调用。
    //gfam::SolverHelper::SolveDocument(pDoc);

    //=====================================================================
    //粘贴完成，提交事务
    bool resCommit = m_opUserTransaction->Commit();

    if (resCommit)
    {
        //将粘贴结果加入选择集，显示为选择状态
        GraphicsNodeReferenceOwnerPtrSet selectedElements;
        FOR_EACH(id, m_pastedElementIds)
        {
            IElement* element = pDoc->GetElement(id);
            DBG_WARN_AND_CONTINUE_UNLESS(element, L"pDoc->GetElement(id) 返回空指针",L"GDMPLab",L"2024-03-30");

            const IElementViewSpecificShapeComponent *pBehavior = element->GetViewSpecificShapeComponent();

            //因为有部分元素被过滤了，比如轴网(TODO: 临时方案，后续会改进得更加合理）
            if (!pBehavior || pBehavior->IsVisibleInModelView(pModelView))
            {
                OwnerPtr<IGraphicsNodeReference> gnodeRef = IGraphicsNodeReference::CreateGraphicsElementShapeReference(id);
                OwnerPtrContainerUtil::AddItem(selectedElements, TransferOwnership(gnodeRef));
            }
        }

        ISelection::Get()->AddGroupGraphicsNodeReference(pDoc, selectedElements);
        std::vector<OwnerPtr<IGraphicsNodeReference>> opGnodRefs;
        OwnerPtrContainerUtil::AddItems(opGnodRefs, selectedElements);
        IHighlights::Get()->AddGraphicsNodeReferences(opGnodRefs);
    }

    pUIDoc->UpdateView();

    MarkFinishStatus(ActionFinishStatus::Successful);
}

void GbmpPasteAction::InitAction(IUiView* pCurrentView)
{
    IUiDocumentViewManager* pUiDocViewManager = IUiDocumentViewManager::Get();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDocViewManager, L"无效的pUiDocViewManager指针",L"GDMPLab",L"2024-03-30");

    IUiDocument* pUIDoc = pUiDocViewManager->GetCurrentUiDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUIDoc, L"pUIDoc为空",L"GDMPLab",L"2024-03-30");

    IUiView* pUIView = pUiDocViewManager->GetCurrentUiView();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUIView, L"pUIView为空",L"GDMPLab",L"2024-03-30");

    IDocument* pDoc = pUIDoc->GetDbDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IModelView* pModelView = pCurrentView->GetModelView();
    if (!(pModelView && GbmpModelViewUtil::IsPlanOrCeilingView(pCurrentView->GetModelView())))
    {
        UiCommonDialog::ShowMessageBox(GBMP_TR(L"粘贴不成功"), GBMP_TR(L"除了在草图编辑模式内，其他非平面视图暂不支持粘贴操作！"), (int)UiCommonDialog::ButtonType::OK);
        MarkFinishStatus(ActionFinishStatus::Successful);
        return;
    }

    //启动事务(一次粘贴操作为一个事务单元)
    m_opUserTransaction = IUserTransaction::Create(pDoc, GBMP_TR(L"粘贴"));
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_opUserTransaction, L"m_opUserTransaction为空",L"GDMPLab",L"2024-03-30");

    vector<ElementId> levelsTo;
    levelsTo.push_back(GbmpModelViewUtil::GetWorkLevelId(pModelView));

    ClipBoard * pClipBoard = ClipBoard::Get();
    DBG_WARN_UNLESS(pClipBoard, L"获取默认的粘贴板管理器失败",L"GDMPLab",L"2024-03-30");
    pClipBoard->SetModelViewId(pModelView->GetBasicInformation()->GetElementId());
    Vector3d defaultPt = pClipBoard->GetMinPt();
    pClipBoard->SetPasteToLevelIds(levelsTo);
    bool ret = pClipBoard->Paste(pDoc, pModelView->GetBasicInformation()->GetElementId(), defaultPt, m_pastedElementIds);
    if (!ret)
    {
        //TODO: 未来需要进一步完善处理失败的情况
        UiCommonDialog::ShowMessageBox(GBMP_TR(L"粘贴"), 
            GBMP_TR(L"粘贴不成功，参考信息: \n") + pClipBoard->GetLastErrorMessage(),
            (int)UiCommonDialog::ButtonType::Yes);

        m_opUserTransaction->Rollback();
        pUIDoc->UpdateView();
        MarkFinishStatus(ActionFinishStatus::Successful);
        return;
    }
    else
    {
        UpdateStoreyLevel(pDoc, levelsTo, m_pastedElementIds);
        InitSourceHelperRect(pCurrentView);
        InitInsertPt(pCurrentView);

        //新文档里只是生成了很多Element对象,需要关联更新一下
        pDoc->GetRegenerator()->RegenerateDocument();
        //立即刷新界面
        pUIDoc->UpdateView();

        //启动拾取粘贴点的子Action
        StartPickPastePointAction(pCurrentView);
    }
}

bool GbmpPasteAction::OnKeyDown(gcmp::IUiView* pCurrentView, int nChar)
{
    if (VK_RETURN == nChar)
    {
        ClipBoard * pClipBoard = ClipBoard::Get();
        DBG_WARN_UNLESS(pClipBoard, L"获取默认的粘贴板管理器失败",L"GDMPLab",L"2024-03-30");
        const Vector3d& insertPt = pClipBoard->GetInsertPt();
        PastePointUpdate(pCurrentView, insertPt);
        PickPastePointActionFinished(pCurrentView, ActionFinishStatus::Successful);
        
        return true;
    }

    return false;
}

void GbmpPasteAction::UpdateStoreyLevel(IDocument* pDoc, const std::vector<ElementId>& levelsTo, const std::vector<ElementId>& pastedElementIds)
{
    FOR_EACH(levelId, levelsTo)
    {
        // 设置Instance的所属楼层
        FOR_EACH(pastedId, pastedElementIds)
        {
            IElement* pElement = pDoc->GetElement(pastedId);
            if (IInstance* pInstance = dynamic_cast<IInstance*>(pElement))
            {
                const UniIdentity& uid = pInstance->GetBasicInformation()->GetCategoryUid();
                //洞口的楼层设置依赖于主体
                if (uid == BuiltInCategoryUniIdentities::BICU_STRUCTURE_WALL_HOLE
                    || uid == BuiltInCategoryUniIdentities::BICU_STRUCTURE_PLATE_HOLE)
                {
                    continue;
                }

                ILevel* pLevelTo = LevelUtils::GetLevelById(pDoc, levelId);
                DBG_WARN_AND_RETURN_VOID_UNLESS(pLevelTo, L"目标文档的粘贴楼层为空！",L"GDMPLab",L"2024-03-30");

                if (!pLevelTo->GetBuildingId().IsValid())
                {
                    std::set<ElementId> excludedLevelIds = ClipBoardUtils::GetAllNonStoreyLevel(pDoc);
                    ILevel* pAssociatedLevel = LevelUtils::GetLevelById(pDoc, IElementPosition::GetAssociatedPlaneId(pInstance));
                    DBG_WARN_AND_RETURN_VOID_UNLESS(pAssociatedLevel, L"pAssociatedLevel is nullptr",L"GDMPLab",L"2024-03-30");
                    ElementId newLevelId = ClipBoardUtils::FindNearestLevelByHeight(pDoc, pAssociatedLevel->GetElevation(), excludedLevelIds);
                    pLevelTo = LevelUtils::GetLevelById(pDoc, newLevelId);
                    DBG_WARN_AND_RETURN_VOID_UNLESS(pLevelTo, L"目标文档的粘贴楼层为空！",L"GDMPLab",L"2024-03-30");
                }

                if (!pInstance->GetSuperInstanceId().IsValid() && pInstance->GetSubInstanceIds().empty())
                    StructureInstanceLevelUtils::SetInstanceStoreyLevel(pInstance, pLevelTo);

            }
        }
    }
}

void GbmpPasteAction::InitSourceHelperRect(IUiView* pUiView)
{
    m_opSourceHelperRect = NEW_AS_OWNER_PTR(HelperRect, pUiView, this);
}

void GbmpPasteAction::ClearSourceHelperRect()
{
    //主动选择时机清理
    if(m_opSourceHelperRect)
    {
        m_opSourceHelperRect = nullptr;
    }
}

void GbmpPasteAction::InitTargetHelperRect(IUiView* pUiView)
{
    m_opTargetHelperRect = NEW_AS_OWNER_PTR(HelperRect, pUiView, this);
}

void GbmpPasteAction::ClearTargetHelperRect()
{
    //主动选择时机清理
    if(m_opTargetHelperRect)
    {
        m_opTargetHelperRect = nullptr;
    }
}

void GbmpPasteAction::InitInsertPt(IUiView* pUiView)
{
    IModelView* pModelView = pUiView->GetModelView();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pModelView, L"view为空",L"GDMPLab",L"2024-03-30");

    IDocument* pDoc = pModelView->GetDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc != nullptr, L"无效的文档",L"GDMPLab",L"2024-03-30");

    ClipBoard * pClipBoard = ClipBoard::Get();
    DBG_WARN_UNLESS(pClipBoard, L"获取默认的粘贴板管理器失败",L"GDMPLab",L"2024-03-30");
    Vector3d inserPt = pClipBoard->GetInsertPt();

    //生成插入点辅助对象
    OwnerPtr<IElementShapeHandleBehavior> pointBehavior = NEW_AS_OWNER_PTR(ClipBoardShapeHandleBehavior, pDoc, inserPt);
    IElementShapeHandle* pointHandle = IElementShapeHandle::Create(TransferOwnership(pointBehavior), pModelView->GetElementId());
    m_insertPtId = pointHandle->GetElementId();
}

void GbmpPasteAction::ClearInsertPt(IDocument* pDoc)
{
    if(!m_insertPtId.IsValid())
        return;

    pDoc->DeleteElement(m_insertPtId);
    m_insertPtId = ElementId::InvalidID;
}

void GbmpPasteAction::MouseMoveUpdate(IUiView* pCurrentView, const Vector3d& pickedPt, const Vector3d& mousePt)
{
    //======================================================================
    //说明（两种情况要分别处理）
    //(1) 情况一：鼠标移动后，不在辅助点的拾取范围内
    //(2）情况二：鼠标移动后，在辅助点的拾取范围内
    //======================================================================
    double tolerance = UiViewUtility::GetPickTolerance(pCurrentView);

    ClipBoard * pClipBoard = ClipBoard::Get();
    DBG_WARN_UNLESS(pClipBoard, L"获取默认的粘贴板管理器失败",L"GDMPLab",L"2024-03-30");
    Vector3d insertPt = pClipBoard->GetInsertPt();
    //暂时忽略Z值
    insertPt.SetZ(mousePt.Z());
    double distance = Vector3dUtils::Distance(insertPt, mousePt);

    //不在辅助点的拾取范围内，只做更新粘贴点的显示
    if ( MathUtils::IsGreaterThan(distance, tolerance, Constants::DOUBLE_EPS))
    {
        PastePointUpdate(pCurrentView, pickedPt);
    }
    //在辅助点的拾取范围内，隐藏跟随鼠标的辅助矩形就可以了
    else
    {
        m_opTargetHelperRect->CleanupTempGraphicsShape();
    }
    
    UpdateView();
}

void GbmpPasteAction::PastePointUpdate(IUiView* pCurrentView, const Vector3d& mousePt)
{
    ClipBoard * pClipBoard = ClipBoard::Get();
    DBG_WARN_UNLESS(pClipBoard, L"获取默认的粘贴板管理器失败",L"GDMPLab",L"2024-03-30");
    //将鼠标的位置做为插入点，计算出包围矩形的左下角lb坐标值
    const Vector3d& minPt = pClipBoard->GetMinPt();
    const Vector3d& insertPt = pClipBoard->GetInsertPt();

    //鼠标左下角点(目前只考虑平面视图)
    Vector3d lbPt = mousePt-(insertPt-minPt);
    m_opTargetHelperRect->Update(lbPt);
}



GbmpPasteAction::HelperRect::HelperRect(const IUiView* pUiView, GbmpPasteAction* pAction)
    :m_wpUiView(pUiView)
    ,m_corners(4)
    ,m_pAction(pAction)
{
    IModelView* pModelView = pUiView->GetModelView();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pModelView, L"view为空",L"GDMPLab",L"2024-03-30");

    IDocument* pDoc = pModelView->GetDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc != nullptr, L"无效的文档",L"GDMPLab",L"2024-03-30");

    m_tmpElementID = UIRenderUtils::RequestTempElement(const_cast<IUiView*>(pUiView));

    ////更新二维包围盒(把GAP考虑进去)
    m_gap = UiViewUtility::ComputeWorldWidthFromPixel(m_wpUiView.Get() , HELPER_RECT_GAP);

    ClipBoard * pClipBoard = ClipBoard::Get();
    DBG_WARN_UNLESS(pClipBoard, L"获取默认的粘贴板管理器失败",L"GDMPLab",L"2024-03-30");

    Coordinate3d localCoor = pClipBoard->GetLocalCoordinate();
    const std::vector<Vector3d>& corners = pClipBoard->GetCorners();
    Vector3d minPt = localCoor.GetWorldPoint(corners[0]);
    Update(minPt);
}

GbmpPasteAction::HelperRect::~HelperRect()
{
    CleanupTempGraphicsShape();
}

void GbmpPasteAction::HelperRect::Update(const Vector3d& lbOfSet)
{
    ClipBoard * pClipBoard = ClipBoard::Get();
    DBG_WARN_UNLESS(pClipBoard, L"获取默认的粘贴板管理器失败",L"GDMPLab",L"2024-03-30");

    const std::vector<Vector3d>& corners = pClipBoard->GetCorners();
    Coordinate3d localCoor = pClipBoard->GetLocalCoordinate();
    Vector3d offsetDist = lbOfSet - localCoor.GetWorldPoint(corners[0]);
    m_corners[0] = localCoor.GetWorldPoint(Vector3d::Create(corners[0].GetX()-m_gap, corners[0].GetY()-m_gap, corners[0].GetZ())) + offsetDist;
    m_corners[1] = localCoor.GetWorldPoint(Vector3d::Create(corners[1].GetX()-m_gap, corners[1].GetY()+m_gap, corners[1].GetZ())) + offsetDist;
    m_corners[2] = localCoor.GetWorldPoint(Vector3d::Create(corners[2].GetX()+m_gap, corners[2].GetY()-m_gap, corners[2].GetZ())) + offsetDist;
    m_corners[3] = localCoor.GetWorldPoint(Vector3d::Create(corners[3].GetX()+m_gap, corners[3].GetY()+m_gap, corners[3].GetZ())) + offsetDist;
    
    if(corners[3].GetX() - corners[1].GetX() < 2 * m_gap + Constants::DOUBLE_EPS 
        && corners[3].GetY() - corners[1].GetY() < 2 * m_gap + Constants::DOUBLE_EPS)//最大点小于等于最小点，不画矩形框。
        return;

    gcmp::OwnerPtr<IGraphicsElementShape> upTempGRep = IGraphicsElementShape::Create(GraphicsRenderLayer::TransientObject );
    DBG_WARN_AND_RETURN_VOID_UNLESS(upTempGRep, L"upTempGRep为空",L"GDMPLab",L"2024-03-30");

    Vector3d lb = m_corners[0];
    Vector3d lt = m_corners[1];
    Vector3d rb = m_corners[2];
    Vector3d rt = m_corners[3];

    upTempGRep->AddChild(TransferOwnership(IGraphicsLine::Create(lb, lt)));
    upTempGRep->AddChild(TransferOwnership(IGraphicsLine::Create(lt, rt)));
    upTempGRep->AddChild(TransferOwnership(IGraphicsLine::Create(rt, rb)));
    upTempGRep->AddChild(TransferOwnership(IGraphicsLine::Create(rb, lb)));

    // 是否需要智能反色
    if (DEBUG_MODE(GbmpPasteHelperRectSmartColor))
    {
        static std::map<RuntimeId, IGraphicsStyle*> graphicsStyleOfRuntimeId;
        
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_wpUiView, L"m_wpUiView为空",L"GDMPLab",L"2024-03-30");
        IModelView* pModelView = m_wpUiView->GetModelView();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pModelView, L"view为空",L"GDMPLab",L"2024-03-30");
        IDocument* pDoc = pModelView->GetDocument();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc != nullptr, L"无效的文档",L"GDMPLab",L"2024-03-30");
        RuntimeId runtimeId = pDoc->GetRuntimeId();
        DBG_WARN_AND_RETURN_VOID_UNLESS(runtimeId.IsValid(), L"无效的runtimeId",L"GDMPLab",L"2024-03-30");
        
        IGraphicsStyle* pStyleElem = nullptr;
        auto it = graphicsStyleOfRuntimeId.find(runtimeId);
        if (it != graphicsStyleOfRuntimeId.end())
        {
            pStyleElem = it->second;
            DBG_WARN_AND_RETURN_VOID_UNLESS(pStyleElem, L"pStyleElem为空",L"GDMPLab",L"2024-03-30");
        }
        else
        {
            OwnerPtr<IGraphicsStyleData> styleData = IGraphicsStyleData::Create();
            DBG_WARN_AND_RETURN_VOID_UNLESS(styleData, L"styleData为空",L"GDMPLab",L"2024-03-30");
            styleData->SetProjectionLineSmartColorMode(SmartColorMode::SmartAntiBackgroundColor);
            pStyleElem = IGraphicsStyle::Create(pDoc, ElementCreationOptions::Transient);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pStyleElem, L"pStyleElem为空",L"GDMPLab",L"2024-03-30");
            pStyleElem->SetGraphicsStyleData(*styleData);
            graphicsStyleOfRuntimeId.insert(std::make_pair(runtimeId, pStyleElem));
        }

        upTempGRep->SetGraphicsStyleId(pStyleElem->GetElementId());
    }

    //m_pAction->DrawTempGraphicsElementShape(TransferOwnership(upTempGRep));
    //m_pAction->UpdateView();
    UIRenderUtils::DrawTempGrep(const_cast<IUiView*>(m_wpUiView.Get()), m_tmpElementID, TransferOwnership(upTempGRep));

    //m_wpUiView->GetUiDocument()->UpdateView();
}

void gcmp::GbmpPasteAction::HelperRect::CleanupTempGraphicsShape()
{
    //m_pAction->CleanupTempGraphicsShape();
    //m_pAction->UpdateView();
    if (m_tmpElementID.IsValid())
        UIRenderUtils::CleanupTempGRep(const_cast<IUiView*>(m_wpUiView.Get()), m_tmpElementID);
}
